package edu.dublbo.app.generator.service;

import edu.dublbo.app.generator.advice.exception.OptErrorException;
import edu.dublbo.app.generator.entity.TBasicModel;
import edu.dublbo.app.generator.entity.TBasicModelDetail;
import edu.dublbo.app.generator.entity.TProjectInfo;
import edu.dublbo.app.generator.mapper.*;
import edu.dublbo.app.generator.result.OptStatus;
import edu.dublbo.app.generator.result.Result;
import edu.dublbo.app.generator.util.Constant;
import edu.dublbo.app.generator.util.SnowflakeIdWorker;
import edu.dublbo.app.generator.util.StrUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.io.*;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.zip.ZipOutputStream;

/**
 * @author habitplus
 * @since 2023/3/12 22:08
 */
@Service
public class ProjectInfoService {
    private final static Logger logger = LoggerFactory.getLogger(ProjectInfoService.class);

    @Resource
    private TProjectInfoMapper mapper;
    @Resource
    private TBasicModelMapper modelMapper;
    @Resource
    private TBasicModelDetailMapper modelDetailMapper;
    @Resource
    private SnowflakeIdWorker idWorker;

    public Result<Object> saveOrUpdate(TProjectInfo info) {
        if (!TProjectInfo.checkValid(info)) {
            return Result.builder()
                    .code(OptStatus.FAIL.code)
                    .msg("输入信息不合法，请按要求输入")
                    .build();
        }

        if (StrUtils.isEmpty(info.getId())) {
            Date now = new Date();
            info.setId(idWorker.nextStringId());
            info.setCreateTime(now);
            info.setCreateUser(Constant.CURRENT_USER);
            info.setDeleteFlag(Constant.LOGIC_NOT_DELETE_VAL);
            mapper.add(info);
        }

        return Result.builder().code(OptStatus.SUCCESS.code).build();
    }

    @Transactional
    public byte[] generateCode(TProjectInfo pro) {

        try (ByteArrayOutputStream os = new ByteArrayOutputStream();
             ZipOutputStream zos = new ZipOutputStream(os)) {
            Result<Object> re = saveOrUpdate(pro);
            // 存数据库
            if (re.getCode() == OptStatus.FAIL.code) {
                throw new OptErrorException(re.getCode(), re.getMsg());
            }
            logger.info("开始生成项目源码：{}", pro);

            List<TProjectInfo.ModuleInfo> moduleList = pro.getModuleList();
            // 初始化生成器
            CodeFileGenV2 generator = CodeFileGenV2.getInstance();
            generator.configProjectData(pro.getProjectName(), pro.getProjectDesc(), pro.getPackageName());
            for (TProjectInfo.ModuleInfo m : moduleList) {
                if (!StrUtils.isBlank(m.getName()) && m.getModelIds() != null) {
                    for (String modelId : m.getModelIds()) {
                        TBasicModel model = modelMapper.get(modelId);
                        // 查询模型明细
                        Map<String, Object> con = new HashMap<>();
                        con.put("modelId", modelId);
                        con.put("_order", "sort_no");
                        List<TBasicModelDetail> details = modelDetailMapper.select(con);
                        if (details != null && details.size() > 0) {
                            generator.zipModuleCode(m.getName(), model, details, zos);
                        } else {
                            logger.warn("当前模型【{}】还没有配置字段，将被跳过", modelId);
                        }
                    }
                }
            }
            // 生成项目配置文件
            generator.zipProjectConfigCode(zos);

            zos.flush();
            zos.finish();
            return os.toByteArray();
        } catch (Exception e) {
            e.printStackTrace();
            throw new OptErrorException(HttpStatus.INTERNAL_SERVER_ERROR.value(), e.getMessage());
        }
    }
}
